home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / comms / other / slrn / slrn_src / src / post.c < prev    next >
C/C++ Source or Header  |  1999-05-14  |  26KB  |  1,186 lines

  1. /* post an article */
  2. /* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
  3.  *
  4.  * This file is part of slrn.
  5.  *
  6.  * Slrn is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation; either version 2, or (at your option) any
  9.  * later version.
  10.  * 
  11.  * Slrn is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * for more details.
  15.  * 
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with Slrn; see the file COPYING.  If not, write to the Free
  18.  * Software Foundation, 59 Temple Place - Suite 330, 
  19.  * Boston, MA  02111-1307, USA.
  20.  */
  21.  
  22. #include "config.h"
  23. #include "slrnfeat.h"
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27.  
  28.  
  29. #ifdef HAVE_UNISTD_H
  30. # include <unistd.h>
  31. #endif
  32.  
  33. #ifdef HAVE_STDLIB_H
  34. # include <stdlib.h>
  35. #endif
  36.  
  37. #include <sys/types.h>
  38. #include <time.h>
  39. #include <slang.h>
  40. #include "jdmacros.h"
  41.  
  42.  
  43. #ifdef VMS
  44. # include "vms.h"
  45. #endif
  46.  
  47. #include "slrn.h"
  48. #include "server.h"
  49. #include "misc.h"
  50. #include "post.h"
  51. #include "group.h"
  52. #include "art.h"
  53. #include "uudecode.h"
  54. #include "util.h"
  55. #include "chmap.h"
  56. #include "menu.h"
  57.  
  58. #if SLRN_HAS_MIME
  59. # include "mime.h"
  60. #endif
  61.  
  62. #define MAX_LINE_BUFLEN    2048
  63.  
  64. char *Slrn_Courtesy_CC_Message = NULL;
  65. char *Slrn_Save_Posts_File;
  66. char *Slrn_Save_Replies_File;
  67. char *Slrn_Last_Message_Id;
  68. char *Slrn_Post_Custom_Headers;
  69. char *Slrn_Failed_Post_Filename;
  70.  
  71. int Slrn_Reject_Long_Lines = 1;
  72. char *Slrn_Postpone_Dir;
  73. int Slrn_Generate_Message_Id = 1;
  74.  
  75. #ifdef VMS
  76. # define SYSTEM_OS_NAME        "VMS"
  77. #else
  78. # ifdef __os2__
  79. #  define SYSTEM_OS_NAME    "OS/2"
  80. # else
  81. #  ifdef AMIGA
  82. #   define SYSTEM_OS_NAME    "Amiga"
  83. #  else
  84. #   ifdef __unix__
  85. #    define SYSTEM_OS_NAME       "UNIX"
  86. #   else
  87. #    if defined(__WIN32__) || defined(__NT__)
  88. #     define SYSTEM_OS_NAME    "Windows"
  89. #    else
  90. #     define SYSTEM_OS_NAME    "UNKNOWN"
  91. #    endif
  92. #   endif
  93. #  endif
  94. # endif
  95. #endif
  96.  
  97. static int postpone_file (char *);
  98.  
  99. #if SLRN_HAS_GEN_MSGID
  100. static char *slrn_create_message_id (void)
  101. {
  102.    unsigned long pid, now;
  103.    static unsigned char baseid[64];
  104.    unsigned char *b, *t, tmp[32];
  105.    char *chars32 = "0123456789abcdefghijklmnopqrstuv";
  106.    static unsigned long last_now;
  107.    
  108.    if (Slrn_Generate_Message_Id == 0)
  109.      return NULL;
  110.  
  111.    while (1)
  112.      {
  113.     if ((Slrn_User_Info.posting_host == NULL)
  114.         || ((time_t) -1 == time ((time_t *)&now)))
  115.       return NULL;
  116.     
  117.     if (now != last_now) break;
  118.     sleep (1);
  119.      }
  120.    last_now = now;
  121.    
  122.    pid = (unsigned long) getpid ();
  123.    now -= 0x28000000;
  124.    
  125.    b = baseid;
  126.    t = tmp;
  127.    while (now)
  128.      {
  129.     *t++ = chars32[now & 0x1F];
  130.     now = now >> 5;
  131.      }
  132.    while (t > tmp)
  133.      {
  134.     t--;
  135.     *b++ = *t;
  136.      }
  137.    *b++ = '.';
  138.    
  139.    t = tmp;
  140.    while (pid)
  141.      {
  142.     *t++ = chars32[pid & 0x1F];
  143.     pid = pid >> 5;
  144.      }
  145.    while (t > tmp)
  146.      {
  147.     t--;
  148.     *b++ = *t;
  149.      }
  150.    
  151.    *b++ = '.';
  152.    t = (unsigned char *) Slrn_User_Info.username;
  153.    if (t != NULL)
  154.      while ((*t != 0) && (b < baseid + sizeof(baseid) - 1)) *b++ = *t++;
  155.    *b = 0;
  156.    
  157.    return (char *) baseid;
  158. }
  159. #endif
  160. void slrn_add_signature (FILE *fp)
  161. {
  162.    FILE *sfp;
  163.    char file[SLRN_MAX_PATH_LEN];
  164.    char buf [256];
  165.    
  166.    if ((sfp = slrn_open_home_file (Slrn_User_Info.signature, "r", file, 0)) != NULL)
  167.      {
  168.     /* Apparantly some RFC suggests the -- \n. */
  169.         fputs ("\n\n-- \n", fp);
  170.     
  171.     /* If signature file already has -- \n, do not add it. */
  172.     if ((NULL != fgets (buf, sizeof (buf), sfp))
  173.         && (0 != strcmp (buf, "-- \n")))
  174.       fputs (buf, fp);
  175.       
  176.         while (NULL != fgets (buf, sizeof(buf), sfp))
  177.       {
  178.          fputs (buf, fp);
  179.       }
  180.         slrn_fclose(sfp);
  181.      }
  182. }
  183.  
  184. static int is_empty_header (char *line)
  185. {
  186.    char *b;
  187.    
  188.    if ((*line == ' ') || (*line == '\t')) return 0;
  189.    
  190.    b = slrn_strchr (line, ':');
  191.    if (b == NULL) return 0;
  192.    
  193.    b = slrn_skip_whitespace (b + 1);
  194.    return (*b == 0);
  195. }
  196.  
  197.  
  198. static int slrn_cc_file (char *file, char *to, char *msgid)
  199. {
  200. #if defined(VMS) || !SLRN_HAS_PIPING
  201.    return -1;
  202. #else
  203. #if defined(IBMPC_SYSTEM)
  204.    char outfile [SLRN_MAX_PATH_LEN];
  205. #endif
  206.    FILE *pp, *fp;
  207.    char line[MAX_LINE_BUFLEN];
  208.    unsigned int cc_line = 0;
  209.    unsigned int linenum;
  210.    char buf [MAX_LINE_BUFLEN];
  211.    unsigned int nth;
  212.    char *l;
  213.  
  214.    if (NULL == (fp = fopen (file, "r")))
  215.      {
  216.     slrn_error ("Unable to open %s.");
  217.     return -1;
  218.      }
  219.    
  220.    /* Look for CC line */
  221.    linenum = 0;
  222.    while ((NULL != fgets (line, sizeof (line) - 1, fp)) && (*line != '\n'))
  223.      {
  224.     linenum++;
  225.     if (0 == slrn_case_strncmp ((unsigned char *)line,
  226.                     (unsigned char *) "Cc: ", 4))
  227.       {
  228.          l = slrn_skip_whitespace (line + 4);
  229.          if (*l && (*l != ',')) cc_line = linenum;
  230.          break;
  231.       }
  232.      }
  233.    
  234.    /* At this point, if all has gone well line contains the cc information */
  235.    
  236.    if (cc_line == 0)
  237.      {
  238.     slrn_fclose (fp);
  239.     return -1;
  240.      }
  241.    
  242. #if defined(IBMPC_SYSTEM)
  243.    pp = slrn_open_tmpfile (outfile, "w");
  244. #else
  245.    pp = slrn_popen (Slrn_SendMail_Command, "w");
  246. #endif
  247.    if (pp == NULL)
  248.      {
  249.     slrn_fclose (fp);
  250.     return -1;
  251.      }
  252.    
  253.    fputs ("To: ", pp);
  254.    
  255.    /* This line consists of a comma separated list of addresses.  In
  256.     * particular, "poster" will be replaced by 'to'.
  257.     */
  258.    l = line + 4;
  259.    nth = 0;
  260.    while (0 == SLextract_list_element (l, nth, ',', buf, sizeof (buf)))
  261.      {
  262.     char *b;
  263.  
  264.     /* Knock whitespace from ends of string */
  265.     b = slrn_skip_whitespace (buf);
  266.     slrn_trim_string (b);
  267.  
  268.     if (nth != 0)
  269.       putc (',', pp);
  270.     
  271.     if ((0 == slrn_case_strcmp ((unsigned char *)b, (unsigned char *)"poster"))
  272.         && (to != NULL))
  273.       b = to;
  274.     
  275.     fputs (b, pp);
  276.     nth++;
  277.      }
  278.  
  279.    putc ('\n', pp);
  280.    rewind (fp);
  281.  
  282.    linenum = 0;
  283.    
  284. #if SLRN_GEN_FROM_EMAIL_HEADER
  285.    fprintf (pp, "From: %s\n", slrn_make_from_string ());
  286. #endif
  287.    
  288.    if (msgid != NULL)
  289.      fprintf (pp, "Message-Id: <slrn%s@%s>\n", 
  290.           msgid, Slrn_User_Info.posting_host);
  291.    
  292.    
  293.    while ((NULL != fgets (line, sizeof (line) - 1, fp)) && (*line != '\n'))
  294.      {
  295.     linenum++;
  296.     if (linenum == cc_line) continue;
  297.     if (is_empty_header (line)) continue;
  298.     if (0 == slrn_case_strncmp ((unsigned char *)line,
  299.                     (unsigned char *) "To: ", 4))
  300.       continue;
  301.     
  302.     /* There is some discussion of this extension to mail headers.  For
  303.      * now, assume that this extension will be adopted.
  304.      */
  305.     if (0 == slrn_case_strncmp ((unsigned char *)line,
  306.                     (unsigned char *) "Newsgroups: ", 12))
  307.       {
  308.          fputs ("Posted-To: ", pp);
  309.          fputs (line + 12, pp);
  310.       }
  311.     else
  312.       fputs (line, pp);
  313.      }
  314.  
  315. # if SLRN_HAS_MIME
  316.    if (Slrn_Use_Mime) slrn_mime_add_headers (pp);
  317. # endif
  318.    
  319.    fputs ("\n", pp);
  320.    
  321.    if ((NULL != Slrn_Courtesy_CC_Message) && (*Slrn_Courtesy_CC_Message))
  322.      {
  323.     slrn_insert_followup_format (Slrn_Courtesy_CC_Message, pp);
  324.     fputs ("\n", pp);
  325.      }
  326.    
  327. # if SLRN_HAS_MIME
  328.    if (Slrn_Use_Mime) fp = slrn_mime_encode (fp);
  329. # endif
  330.    
  331.    while (NULL != fgets (line, sizeof (line) - 1, fp))
  332.      {
  333.     fputs (line, pp);
  334.      }
  335.    slrn_fclose (fp);
  336. # if defined(IBMPC_SYSTEM)
  337.    slrn_fclose (pp);
  338.    sprintf (buf, "%s %s", Slrn_SendMail_Command, outfile);
  339.    slrn_posix_system (buf, 0);
  340. # else
  341.    slrn_pclose (pp);
  342. # endif
  343.    return 0;
  344. #endif                       /* NOT VMS */
  345. }
  346.  
  347. /* Returns -1 upon error, 0, if ok, 1 if needs repair, 2 is warning is issued */
  348. static int check_file_for_posting (char *file)
  349. {
  350.    char line[MAX_LINE_BUFLEN], *the_line;
  351.    FILE *fp;
  352.    unsigned int num;
  353.    char *err;
  354.    int newsgroups_found, subject_found, only_warning;
  355.    char ch;
  356.    char *colon;
  357.    
  358.    only_warning = newsgroups_found = subject_found = 0;
  359.    err = NULL;
  360.    fp = fopen (file, "r");
  361.    
  362.    if (fp == NULL)
  363.      {
  364.     slrn_error ("Unable to open %s", file);
  365.     return -1;
  366.      }
  367.    
  368.    the_line = line;
  369.    
  370.    /* scan the header */
  371.    num = 0;
  372.    while (NULL != fgets (line, sizeof (line), fp))
  373.      {
  374.     ch = *line;    
  375.     num++;
  376.     if ((ch == ' ') || (ch == '\t') || (ch == '\n'))
  377.       {
  378.          if (num == 1) 
  379.            {
  380.           err = "The first line must begin with a header.";
  381.           break;
  382.            }
  383.          if (ch == '\n') break;
  384.          
  385.          continue;
  386.       }
  387.     
  388.     if (NULL == (c